package com.bootcamp.s2_0922.frontend._1011;

import java.util.Scanner;

/**
 * 从键盘上输入年和月, 打印该月的日历
 */
public class Test {
    public static void main(String[] args) {
        //1) 从键盘上输入年和月,
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入年和月");
        int year = sc.nextInt();        //2021
        int month = sc.nextInt();       //10

        //2) 打印该月的日历
        //先打印本月日历的第一行(表头)
        System.out.println("一\t二\t三\t四\t五\t六\t日\t");
        //打印本 月的数字
        //定义计数器变量
        int count = 0;
        //确定本月1号是星期几
        int weekday = getWeekDay(year, month, 1);
        //打印第一行前面的空白
        for (int i = 1; i < weekday; i++) {
            System.out.print("\t");
            count++;    //第一行前面的空白也需要计数
        }
        //确定本月的天数
        int days = getMonthDays(year, month);
        //打印本月的数字
        for (int i = 1; i <= days; i++) {
            System.out.print(i + "\t");
            count++;    //统计打印数字的数量
            //判断是否需要换行
            if (count % 7 == 0) {
                System.out.println();   //换行
            }
        }
    }

    //返回指定日期是星期几, 通过参数接收一个日期(年,月, 日),
    //返回数字1~7表示星期一~星期日
    private static int getWeekDay(int year, int month, int day) {
        //2021 11 23
        //已知1900-1-1 是星期一, 计算 year-month-day是星期几, 首先要计算从1900-1-1 到这个日期经过的总天数, 总天数对7求余, 余数为1表示星期一, 余数为2表示星期二....余数6表示星期六, 余数为0表示星期日
        int sum = 0;   //定义变量保存总天数
        //先累加整年的天数[1900, year)
        for (int i = 1900; i < year; i++) {
            sum += isLeap(i) ? 366 : 365;
        }

        //再累加year这一年整月的天数[ 1, month )
        for (int i = 1; i < month; i++) {
            sum += getMonthDays(year, i);
        }

        //最后累加year-month这月的天数
        sum += day;

        //总天数对7求余
        int r = sum % 7;

        return r == 0 ? 7 : r;
    }

    /**
     * 计算指定月份的天数
     *
     * @param year  接收年
     * @param month 接收月
     * @return 指定月份的天数
     */
    private static int getMonthDays(int year, int month) {
        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                return 31;
            case 4:
            case 6:
            case 9:
            case 11:
                return 30;
            case 2:
                //闰年有29天,平年有28天
                return isLeap(year) ? 29 : 28;
        }
        return 0;
    }

    //定义方法判断闰年
    private static boolean isLeap(int year) {
        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    }
}
